-
Notifications
You must be signed in to change notification settings - Fork 216
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[experimental] update test-demo with version with lambdas #1146
base: develop
Are you sure you want to change the base?
[experimental] update test-demo with version with lambdas #1146
Conversation
return true; | ||
}, | ||
box_visitor | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This shows how the function could be used.
5 lambdas (2 expand, 2 overlaps, 1 main) plus an optional lambda (called per box),
instead of the earlier policies with apply
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A lot better! I prefer function objects over objects with apply()
function.
One nitpick. This is not quadtree, it's kdtree, a node in quadtree is divided into 4 children, here a division is done into 2, once per dimension. Furthermore partition is k-dimensional, quadtree is 2-dimensional.
Side note, I was thinking about redesigning the API for a long time and use features from the rtree. Note e.g. that in your example you shouldn't be forced to pass function objects defining how to expand a box or perform intersection. These operations are always done the same way. We probably also never use box visitors, besides debugging or visualization so box visitor could be hidden as well. The only additional information in your example that's needed is the way of getting a box from item (taking point from point should work by default). In rtree this is done by IndexableGetter. There are also additional things like the type of operation (in this case intersects) and strategies (for defining CS) but they could be optional as well. I'm not saying to do this, only sharing what I was thinking about.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
I think it's not exactly a kdtree either. You are right, we divide into halves and not into 4. But always at the middle, in kdtree that it is not necessarily the case. Anyway, I can rename it of course. But it cannot be called partition
... (unless we replace it).
Plus we have those additional boxes for cases where geometries exceed the halves. But sure, they are not part of the quadtree either.
I see your point. Yes, taking the box from an object is usually enough. Or point. But it could be done in a different way as well. For example: a box with a margin (for (max) distance calculations). It's flexible now. But that flexibility is probably used rarely, if at all. We use partition only internally, I think. It was introduced before our index so at that moment it was not a choice. So yes, it can be a bit simpler. The box visitor is indeed only used for debugging (at least at this moment).
Anyway, additionally, if we go this way, we don't need those visitor-adaptor(s), we can deprecate the old implementation and let the new one immediately use function objects.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Splitting planes can be placed at various locations in a kd-tree. Classic approach is to place them at the median object. Another strategy is to cut empty space out. There is also version using surface area heuristic. There are probably more. It depends on a use case. Splitting in half is probably a poor choice in general good only for objects distributed uniformly but such tree is still kd-tree.
Btw, in kd-tree splitting doesn't have to be done one dimension after another. The space can be split e.g. in X axis cutting out empty space and then again in X axis at the middle object, etc. But no matter what strategy is used this is still kd-tree.
Regarding quadtrees. There are versions of quadtrees that have splitting planes at different locations than geometric middle of a node. AFAIR there are also quadtrees with child nodes partially overlapping each other which makes them similar to rtrees.
Obviously partition is neither quadtree nor kd-tree because it's not a data structure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're completely right, it's not a data structure. Thanks for the backgrounds. I will just keep the partition
name.
As a work-title it's now temporarily lambda_partition
.
I will not merge this PR. It is a discussion piece. If we agree and things are clear, I'll change the original (copy, and deprecate the old one)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's used internally around 12 times.
Unfortunately it's not in namespace detail
so officially it is part of the interface.
> | ||
bool quadtree_partition(ForwardRange1 const& forward_range1, | ||
ForwardRange2 const& forward_range2, | ||
const std::function |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd avoid using std::function
because it's heavy. Why did you decide to use it over a function object?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The compiler error messages are clearer.
I was not aware that it is heavier.
template <typename F> | ||
struct adapt_partition_visitor | ||
{ | ||
const F& m_f; | ||
|
||
explicit adapt_partition_visitor(const F& f) | ||
: m_f(f) | ||
{} | ||
|
||
template<typename T1, typename T2> | ||
bool apply(T1 const& i1, T2 const& i2) const | ||
{ | ||
return m_f(i1, i2); | ||
} | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All of the adaptors could probably be replaced with one simply forwarding parameters to function object:
template <typename F>
struct adapt_partition_visitor
{
F m_f;
explicit adapt_partition_visitor(F&& f)
: m_f(std::move(f))
{}
template <typename ...Ts>
decltype(auto) apply(Ts&& ...is) const
{
return m_f(std::forward<Ts>(is)...);
}
};
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, works perfectly. Thanks!
✔️
33e1218
to
dc9c4cc
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, this is cool! I am OK with merging now.
I will have a deeper look next week.
Regarding the name I also agree it is neither quad nor kd-tree (it is not a tree at all of course and it actually combines the default splitting strategy "cut in middle" of quad trees with the kd-tree per-dimension partitioning). So I think it is better to just call it "partitioning".
test/robustness/within/Jamfile
Outdated
@@ -0,0 +1,17 @@ | |||
# Boost.Geometry (aka GGL, Generic Geometry Library) | |||
# Robustness Test - convex_hull |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is not convex hull, typo?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, I copied another file and forgot to adapt the title.
✔️ fixed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, this is cool! I am OK with merging now. I will have a deeper look next week. Regarding the name I also agree it is neither quad nor kd-tree (it is not a tree at all of course and it actually combines the default splitting strategy "cut in middle" of quad trees with the kd-tree per-dimension partitioning). So I think it is better to just call it "partitioning".
Renamed now to partitioning
(currently in namespace experimental
)
detail::partition::include_all_policy | ||
>::apply(forward_range1, forward_range2, av, | ||
aev1, aov1, | ||
aev2, aov2, 16, apbv); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe add a comment that 16 is the end of the iteration (the max number of points in a partition box)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed it to an options structure, as I planned earlier.
Is something like this fine?
✔️
17ae254
to
7251ca5
Compare
7251ca5
to
0b4bfe7
Compare
I updated this PR:
It's still in namespace |
{ | ||
return turn.is_turn_traversable && ! turn.within_original; | ||
} | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doing this, I noticed that we sometimes use the include_turn_policy
but sometimes have it in the get_box/overlaps functors. For that reason, if this functionality is always there, we could also choose to get rid of these options.
(the one left is the default partition size but we can specify it as an optional parameter).
What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I omitted it, it was really just about expanding the bounding box.
template | ||
< | ||
typename BoxType, | ||
typename ForwardRange, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This version is added, it uses only one ForwardRange
which is partitioned with itself
0b4bfe7
to
d789038
Compare
I'm now using
Then we can deprecate In a next Boost version, we can delete it and rename |
gcc 5 now reports:
This is inconvenient and wrong, it is there and correct. And it is only for the second lambda... Any idea how to circumvent this? |
It confuses the two overloads of |
Hi, this is an experimental version of partition using lambdas.
For demonstration and evaluation purposes.
I'm curious to your findings.